﻿
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;

namespace Crypt_Tranceiver
{
    public class AsynchronousClient
    {
        // The port number for the remote device.   
        public static int port = 10240;
        // The response from the remote device.   
        private static String response = String.Empty;

        public bool connected = false;

        public static Socket StartClient(String server, int port)
        {  
            try
            {
                IPHostEntry ipHostInfo = Dns.GetHostEntry(server);
                AsynchronousClient.port = port;
                IPAddress ipAddress = ipHostInfo.AddressList[0];
                ipAddress = Dns.GetHostAddresses(server)[0];
                IPEndPoint remoteEP = new IPEndPoint(ipAddress, AsynchronousClient.port);
                // 创建 TCP/IP socket.   
                Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                // 连接远端   
                client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);
                return client;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                return null;
            }
        }
        private static void ConnectCallback(IAsyncResult ar)
        {
            try
            {
                Socket client = (Socket)ar.AsyncState;
                // 完成连接过程 
                client.EndConnect(ar);
                Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint.ToString());
                work_list status = new work_list();
                status.Oper = work_list.CLIENT_CONNECT;
                status.Req_Res = work_list.DIR_REQ;
                status.Date = client.RemoteEndPoint.ToString();
                status.Length = status.Date.Length;
                status.Error = work_list.ERROR_OK;
                status.Direction = work_list.DIR_OUT;
                //通知主线程连接完成
                Form_Main.status_mutex.WaitOne();
                Form_Main.status_inlist.Enqueue(status);
                Form_Main.status_mutex.ReleaseMutex();
                Receive(client);
            }
            catch (System.Net.Sockets.SocketException e)
            {
                //捕获错误
                work_list status = new work_list();
                status.Oper = work_list.CLIENT_CONNECT;
                status.Req_Res = work_list.DIR_REQ;
                status.Error = work_list.ERROR_NOK;
                status.Date = e.Message;
                status.Length = status.Date.Length;
                status.Direction = work_list.DIR_OUT;
                //通知主线程捕获错误
                Form_Main.status_mutex.WaitOne();
                Form_Main.status_inlist.Enqueue(status);
                Form_Main.status_mutex.ReleaseMutex();
                Console.WriteLine(e.ToString());
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
        private static void Receive(Socket client)
        {
            try
            {   
                StateObject state = new StateObject();
                state.workSocket = client;
                // 开始接收数据
                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
        private static void ReceiveCallback(IAsyncResult ar)
        {
            try
            {  
                StateObject state = (StateObject)ar.AsyncState;
                Socket client = state.workSocket;
                // 接受数据.   
                int bytesRead = client.EndReceive(ar);
                if (bytesRead > 0)
                {
                    String content = Encoding.UTF8.GetString(state.buffer, 0, bytesRead);
                    work_list item = new work_list();
                    //对数据包解码
                    item = Form_Main.bg_message_decode(content);
                    //将数据放入接收队列
                    Form_Main.tcp_in_mutex.WaitOne();
                    Form_Main.tcp_inlist.Enqueue(item);
                    Form_Main.tcp_in_mutex.ReleaseMutex();
                }
                //继续接受数据
                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
        public static void Send(Socket client, String data)
        { 
            byte[] byteData = Encoding.UTF8.GetBytes(data);
            //开始发送数据 
            try
            {
                client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), client);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
        private static void SendCallback(IAsyncResult ar)
        {
            try
            {  
                Socket client = (Socket)ar.AsyncState;
                //完成数据发送  
                int bytesSent = client.EndSend(ar);
                Console.WriteLine("Sent {0} bytes to server.", bytesSent); 
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }
}